package com.huanzhidadi.ratelimiter;

import com.huanzhidadi.ratelimiter.limiter.LeakyBucketRateLimiter;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class TestDemo {
    public static void main(String[] args) throws InterruptedException {
        System.out.println(LocalDateTime.now());
        System.out.println(LocalDateTime.now().toEpochSecond(ZoneOffset.UTC));
        System.out.println(LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) / 10);
        System.out.println(LocalDateTime.now().toEpochSecond(ZoneOffset.UTC) / 10 * 10);
        testLeakyBucketRateLimiter();
    }

    /**这并不是一个完整的漏桶算法的实现，以上代码中只是对流量是否会被抛弃进行校验
     * 即tryAcquire返回true表示漏桶未满，否则表示漏桶已满丢弃请求。
     想要以恒定的速率漏出流量，通常还应配合一个FIFO队列来实现，当tryAcquire返回true时，将请求入队
     然后再以固定频率从队列中取出请求进行处理。示例代码如下*/
    public static void testLeakyBucketRateLimiter() throws InterruptedException {
        ScheduledExecutorService scheduledExecutorService = Executors.newSingleThreadScheduledExecutor();
        ExecutorService singleThread = Executors.newSingleThreadExecutor();

        LeakyBucketRateLimiter rateLimiter = new LeakyBucketRateLimiter(10, 2);
        // 存储流量的队列
        Queue<Integer> queue = new LinkedList<>();
        // 模拟请求  不确定速率注水
        //因为是newSingleThreadExecutor
        singleThread.execute(() -> {
            int count = 0;
            System.out.println(Thread.currentThread().getName()+"线程");
            while (true) {
                // 模拟每秒钟产生的随机流量
                int batch = new Random().nextInt(4);
                System.out.println("batch: " + batch);
                for (int i=0; i<batch; i++) {
                    count++;
                    //判断桶满没有满，如果满了就拒绝，如果没满就不限流
                    boolean flag = rateLimiter.tryAcquire();
                    if (flag) {
                        queue.offer(count);
                        System.out.println(count + "--------流量被放行--------");
                    } else {
                        System.out.println(count + "流量被限制");
                    }
                }
                System.out.println("当前queue大小：" + queue.size());
                try {
                    /*long sleep = (long) (Math.random() * 1000);
                    System.out.println("sleep: " + sleep);
                    Thread.sleep(sleep);*/
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });

        // 模拟处理请求 固定速率漏水
        scheduledExecutorService.scheduleAtFixedRate(() -> {
            if (!queue.isEmpty()) {
                System.out.println(queue.poll() + "被处理");
            }
        }, 0, 100, TimeUnit.MILLISECONDS);

        // 保证主线程不会退出
        while (true) {
            Thread.sleep(10000);
        }
    }
}
